package com.gitee.wsl.struct.grammar.ast.process.constraints.ext


import com.gitee.wsl.ext.string.isEmptyOrSpaces
import com.gitee.wsl.text.reader.line.LookaheadText
import com.gitee.wsl.struct.grammar.ast.process.constraints.TextReadConstraints


fun TextReadConstraints.isStartOfLineWithConstraints(pos: LookaheadText.Position): Boolean {
    return pos.offsetInCurrentLine == getCharsEaten(pos.currentLineText)
}

fun LookaheadText.Position.getFirstNonWhitespaceLinePos(eolsToSkip: Int): LookaheadText.Position? {
    var currentPos = this
    repeat(eolsToSkip - 1) {
        currentPos = nextLinePosition() ?: return null
    }
    while (currentPos.charsToNonWhitespace() == null) {
        currentPos = currentPos.nextLinePosition()
            ?: return null
    }
    return currentPos
}

fun TextReadConstraints.applyToNextLineAndAddModifiers(pos: LookaheadText.Position): TextReadConstraints {
    require(pos.offsetInCurrentLine == -1)

    var result = applyToNextLine(pos)
    val line = pos.currentLineText

    while (true) {
        val offset = result.getCharsEaten(line)
        result = result.addModifierIfNeeded(pos.nextPosition(1 + offset)) ?: break
    }

    return result
}


fun TextReadConstraints.findNonEmptyLineWithSameConstraints(pos: LookaheadText.Position): LookaheadText.Position? {
    var currentPos = pos

    while (true) {
//      currentPos = currentPos.nextLinePosition() ?: return null

        val nextLineConstraints = applyToNextLineAndAddModifiers(currentPos)
        // kinda equals
        if (!(nextLineConstraints.upstreamWith(this) && nextLineConstraints.extendsPrev(this))) {
            return null
        }

        val stringAfterConstraints = nextLineConstraints.eatItselfFromString(currentPos.currentLineText)

        if (!stringAfterConstraints.isEmptyOrSpaces()) {
            return currentPos
        } else {
            currentPos = currentPos.nextLinePosition() ?: return null
        }
    }
}
